﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.ComponentModel;

namespace GFrame.Utility
{
    /// <summary>
    /// 延迟器回调事件类
    /// Jay.Gu
    /// 2008-12-22
    /// </summary>
    public class DeferredEvent
    {
        /// <summary>
        /// 回传事件参数
        /// </summary>
        public class DeferredEventArgs : EventArgs
        {
            public readonly object CallBackValue;
            public readonly object[] args;
            public readonly Exception ex;

            public DeferredEventArgs(object callbackValue, object[] callbacllArgs)
            {
                CallBackValue = callbackValue;
                args = callbacllArgs;
            }

            public DeferredEventArgs(object callbackValue)
            {
                CallBackValue = callbackValue;
            }

            public DeferredEventArgs(object callbackValue, Exception Err)
            {
                CallBackValue = callbackValue;
                ex = Err;
            }

            public DeferredEventArgs(object callbackValue, Exception Err, object[] callbacllArgs)
            {
                CallBackValue = callbackValue;
                ex = Err;
                args = callbacllArgs;
            }
        }

        public delegate void DeferredCallBack(object sender, DeferredEventArgs e);

        public event DeferredCallBack CallBackEvent;

        public virtual void OnCallBack(DeferredEventArgs e)
        {
            if (CallBackEvent != null)
                CallBackEvent(this, e);
        }



        public void RaiseEvent(object CallbackValue)
        {
            DeferredEventArgs e = new DeferredEventArgs(CallbackValue);
            OnCallBack(e);
        }

        public void RaiseEvent(object CallbackValue, Exception ex)
        {
            DeferredEventArgs e = new DeferredEventArgs(CallbackValue, ex);
            OnCallBack(e);
        }

        public void RaiseEvent(object CallbackValue, Exception ex, object[] CallbackArgs)
        {
            DeferredEventArgs e = new DeferredEventArgs(CallbackValue, ex, CallbackArgs);
            OnCallBack(e);
        }

    }


    /// <summary>
    /// 用于非阻塞操作的延迟器
    /// Jay.Gu
    /// 2008-12-22
    /// </summary>
    public class Deferred
    {

        private DeferredEvent _deferEvent = new DeferredEvent();
        
        /// <summary>
        /// 添加回调方法
        /// </summary>
        /// <param name="callback"></param>
        public virtual void AddCallBack(DeferredEvent.DeferredCallBack callback, params object [] Paramlist)
        {
            _deferEvent.CallBackEvent += new DeferredEvent.DeferredCallBack(callback);
        }

        private Dictionary<string, object> _dicParam = new Dictionary<string, object>();

        /// <summary>
        /// 添加参数
        /// </summary>
        /// <param name="Name">名称</param>
        /// <param name="Value">值</param>
        public virtual Deferred AddParam(string Name, object Value)
        {
            if(_dicParam.ContainsKey(Name))
                _dicParam[Name] = Value;
            else
                _dicParam.Add(Name, Value);

            return this;

        }

        /// <summary>
        /// 参数列表
        /// </summary>
        public Dictionary<string, object> Params
        {
            set
            {
                _dicParam = value;
            }
            get
            {
                return _dicParam;
            }
        }

        /// <summary>
        /// 清除所有参数
        /// </summary>
        public virtual void ClearParam()
        {
            _dicParam.Clear();
        }

        public void CallBack(object Value)
        {
            _deferEvent.RaiseEvent(Value);
        }

        public void CallErrorBack(object Value, Exception Error)
        {
            _deferEvent.RaiseEvent(Value, Error);
        }

        /// <summary>
        /// 执行其他方法
        /// </summary>
        /// <param name="doit"></param>
        /// <param name="CallBack">是否自动触发回调</param>
        public void Do(ParameterizedThreadStart doit, bool CallBack)
        {
            //ThreadStart ts = new ThreadStart(doit);

            //LocalDataStoreSlot secSlot = Thread.GetNamedDataSlot("value");

            Thread t = new Thread(doit);

            t.Start(_dicParam);

            if (CallBack)
            {
                t.Join();
                _deferEvent.RaiseEvent(true);
            }
        }

    }
}
